/*
 * Created by Gibbs on 2021/1/1.
 * Copyright (c) 2021 Gibbs. All rights reserved.
 */

#ifndef GPLAYER_MESSAGESOURCE_H
#define GPLAYER_MESSAGESOURCE_H

#include "ConcurrentQueue.h"

#define MAX_BUFFER_PACKET_SIZE 25 * 60
#define MIN_BUFFER_PACKET_SIZE 25 * 5
#define MAX_BUFFER_FRAME_SIZE  5
#define MIN_BUFFER_FRAME_SIZE  0

#define MSG_DOMAIN_ERROR      0
#define MSG_DOMAIN_STATE      1
#define MSG_DOMAIN_TIME       2
#define MSG_DOMAIN_BUFFER     3
#define MSG_DOMAIN_DEMUXING   4
#define MSG_DOMAIN_DECODING   5
#define MSG_DOMAIN_COMPLETE   6
#define MSG_DOMAIN_SEEK       7

#define MSG_ERROR_DEMUXING    0
#define MSG_ERROR_DECODING    1
#define MSG_ERROR_RENDERING   2
#define MSG_ERROR_SEEK        3

#define MSG_DEMUXING_INIT     0
#define MSG_DEMUXING_DESTROY  1
#define MSG_DEMUXING_EOF      2

#define MSG_SEEK_START        0
#define MSG_SEEK_END          1

#define STATE_IDLE            0
#define STATE_INITIALIZED     1
#define STATE_PREPARING       2
#define STATE_PREPARED        3
#define STATE_STARTED         4
#define STATE_PAUSED          5
#define STATE_STOPPED         6
#define STATE_COMPLETED       7
#define STATE_END             8
#define STATE_ERROR           9


class Message {
public:
    Message() {
        reset();
    }

    Message(int from, int type, long extra) {
        this->from = from;
        this->type = type;
        this->extra = extra;
    }

    void reset() {
        this->from = -1;
        this->type = -1;
        this->extra = -1;
    }

    void reset(Message *input) {
        this->from = input->from;
        this->type = input->type;
        this->extra = input->extra;
    }

    const char* toString() {
        switch (from) {
            case MSG_DOMAIN_ERROR:
                return "error";
            case MSG_DOMAIN_STATE:
                return "state";
            case MSG_DOMAIN_TIME:
                return "position";
            case MSG_DOMAIN_BUFFER:
                return "buffer";
            case MSG_DOMAIN_DEMUXING:
                return "demuxing";
            case MSG_DOMAIN_DECODING:
                return "decoding";
            case MSG_DOMAIN_COMPLETE:
                return "complete";
            case MSG_DOMAIN_SEEK:
                return "seek";
        }
        return "unknown";
    }

    int from;
    int type;
    long extra;
};

class MessageSource {
public:
    MessageSource();

    ~MessageSource();

    unsigned long pushMessage(int from, int type, long extra);

    unsigned long readMessage(Message **message);

    void flush();

    void quit();

    unsigned long size();

private:
    ConcurrentQueue<Message *> *msgQueue;
    int currentPosition = 0;
    bool isBuffering = false;
};


#endif //GPLAYER_MESSAGESOURCE_H
